package com.topsec.erp.util;

/**
 * 类说明：
 *
 * @Description TODO：代办事项的标记，一般生成类或方法都需要添加描述
 * @Idea IntelliJ IDEA
 * @Since JDK：1.8.0_102
 * @Date 2019-11-25 15:42
 * @Program erp
 * @ClassName DataLenCheckHelper
 * @Version V1.0
 * @Author hyq
 */

import com.topsec.erp.util.CustomAnnotation.DataIsEmpty;
import com.topsec.erp.util.CustomAnnotation.DataLen;
import com.topsec.erp.util.CustomAnnotation.DataMaxSize;
import com.topsec.erp.util.CustomAnnotation.DataMinSize;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;


/**
 * 说明：校验数据长度的帮助类
 *
 * @author hyq
 * @date 2019/11/25 15:54
 */
public class DataCheckHelperUtil {

    /**
     * 校验数据属性的长度
     */
    @SuppressWarnings("rawtypes")
    public static void checkAttributeValueLen(Object obj) throws Exception {
        if (null != obj) {
            // 得到class
            Class cls = obj.getClass();
            System.out.println("校验对象中参数的数据长度是否符合要求,校验对象:" + cls.getName());
            // 得到所有属性
            Field[] fields = cls.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {// 遍历
                try {
                    // 得到属性
                    Field field = fields[i];
                    // 获取字段上的注解集合
                    Annotation[] anns = field.getAnnotations();
                    DataLen dataLen = null;
                    for (Annotation ann : anns) {
                        if (ann instanceof DataLen) {
                            dataLen = (DataLen) ann;
                        }
                    }

                    // 判断该属性是否有校验数据长度的注解
                    if (null != dataLen) {
                        // 打开私有访问
                        field.setAccessible(true);
                        // 获取属性
                        String name = field.getName();
                        // 获取属性值
                        Object value = field.get(obj);
                        // 指定的长度
                        int len = dataLen.valueLen();
                        // 数据的长度
                        int vaLen = 0;
                        String data = null;
                        // 一个个赋值
                        if (null != value && value instanceof String) {
                            data = (String) value;
                            vaLen = data.length();
                        }

                        if (vaLen != len) {
                            System.out.println("对象:" + cls.getName() + "中存在不符合条件的参数,参数名:" + name
                                    + "参数值:" + data + "指定的数据长度:" + len + "实际长度:" + vaLen + "不符合条件");
                            throw new Exception();
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 注解验证电泳方法
     *
     * @param bean 验证的实体
     * @return
     * @author zhy
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> validate(Object bean) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("message", "验证通过");
        result.put("result", true);
        Class<?> cls = bean.getClass();

        // 检测field是否存在
        try {
            // 获取实体字段集合
            Field[] fields = cls.getDeclaredFields();
            for (Field f : fields) {
                // 通过反射获取该属性对应的值
                f.setAccessible(true);
                // 获取字段值
                Object value = f.get(bean);
                // 获取字段上的注解集合
                Annotation[] arrayAno = f.getAnnotations();
                for (Annotation annotation : arrayAno) {
                    // 获取注解类型（注解类的Class）
                    Class<?> clazz = annotation.annotationType();
                    // 获取注解类中的方法集合
                    Method[] methodArray = clazz.getDeclaredMethods();
                    for (Method method : methodArray) {
                        // 获取方法名
                        String methodName = method.getName();
                        // 过滤错误提示方法的调用
                        if (methodName.equals("message")) {
                            continue;
                        }
                        // 初始化注解验证的方法处理类 （我的处理方法卸载本类中）
                        Object obj = DataCheckHelperUtil.class.newInstance();
                        // 获取方法
                        try {
                            // 根据方法名获取该方法
                            Method m = obj.getClass().getDeclaredMethod(methodName, Object.class, Field.class);
                            // 调用该方法
                            result = (Map<String, Object>) m.invoke(obj, value, f);
                            /* 验证结果 有一处失败则退出 */
                            if (result.get("result").equals(false)) {
                                // 获取属性
                                String name = f.getName();
                                // 属性值
                                String data = null;
                                if (null != value && value instanceof String) {
                                    data = (String) value;
                                }
                                if (null != m) {
                                    if (methodName.equals("valueLen")) { // 指定长度
                                        System.out.println("对象:" + cls.getName() + "中存在不符合条件的参数,参数名:" + name
                                                + "参数值:" + data + "指定的数据长度不符合指定要求");
                                    } else if (methodName.equals("min")) {
                                        System.out.println("对象:" + cls.getName() + "中存在不符合条件的参数,参数名:" + name
                                                + "参数值:" + data + "指定的数据的【 最小值 】未达到指定要求");
                                    } else if (methodName.equals("max")) {
                                        System.out.println("对象:" + cls.getName() + "中存在不符合条件的参数,参数名:" + name
                                                + "参数值:" + data + "指定的数据的【 最大值 】超过到指定要求");
                                    }
                                }
                                return result;
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            System.out.println("找不到该方法:" + methodName);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("验证出错");
        }
        return result;
    }


    /**
     * 验证是否空值
     *
     * @param value 参数值
     * @param field 字段
     * @return
     * @author zhy
     */
    public Map<String, Object> isEmpty(Object value, Field field) {
        Map<String, Object> validateResult = new HashMap<String, Object>();
        DataIsEmpty annotation = field.getAnnotation(DataIsEmpty.class);
        if (value == null || value.equals("")) {
            validateResult.put("message", field.getName() + annotation.message());
            validateResult.put("result", false);
        } else {
            validateResult.put("message", "验证通过");
            validateResult.put("result", true);
        }
        return validateResult;
    }

    /**
     * 验证是否为指定长度
     *
     * @param value 参数值
     * @param field 字段
     * @return
     * @author zhy
     */
    public Map<String, Object> valueLen(Object value, Field field) {
        Map<String, Object> validateResult = new HashMap<String, Object>();
        DataLen annotation = field.getAnnotation(DataLen.class);
        // 注解中指定的长度
        int i = annotation.valueLen();
        // 属性名称
        String methodName = field.getName();
        // 注解接口中的默认值
        String message = annotation.message();
        if (value != null && value.toString().length() == i) {
            validateResult.put("message", "验证通过");
            validateResult.put("result", true);
        } else {
            validateResult.put("message", methodName + message);
            validateResult.put("result", false);
        }
        return validateResult;
    }

    /**
     * 验证最小值
     *
     * @param value 参数值
     * @param field 字段
     * @return
     * @author zhy
     */
    public Map<String, Object> min(Object value, Field field) {
        Map<String, Object> validateResult = new HashMap<String, Object>();
        DataMinSize annotation = field.getAnnotation(DataMinSize.class);
        // 注解中指定的长度
        int min = annotation.min();
        // 属性名称
        String methodName = field.getName();
        // 注解接口中的默认值
        String message = annotation.message();
        if (value != null && value.toString().length() > min) {
            validateResult.put("message", "验证通过");
            validateResult.put("result", true);
        } else {
            validateResult.put("message", methodName + message);
            validateResult.put("result", false);
        }
        return validateResult;
    }

    /**
     * 验证最大值
     *
     * @param value 参数值
     * @param field 字段
     * @return
     * @author zhy
     */
    public Map<String, Object> max(Object value, Field field) {
        Map<String, Object> validateResult = new HashMap<String, Object>();
        DataMaxSize annotation = field.getAnnotation(DataMaxSize.class);
        // 注解中指定的长度
        int max = annotation.max();
        // 属性名称
        String methodName = field.getName();
        // 注解接口中的默认值
        String message = annotation.message();
        if (value != null && value.toString().length() > max) {
            validateResult.put("message", methodName + message);
            validateResult.put("result", false);
        } else {
            validateResult.put("message", "验证通过");
            validateResult.put("result", true);
        }
        return validateResult;
    }

}